﻿/**
    J-Focus 0.3.1
    @author vimfung
    @see https://sourceforge.net/projects/jfocus/
**/
(function (window) {
    var _startupTime = 0;
    var _application = null;

    //在IE下JS的Array不支持IndexOf方法，需要进行实现。
    if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function (el, index) {
            var n = this.length >>> 0, i = ~ ~index;
            if (i < 0) i += n;
            for (; i < n; i++) if (i in this && this[i] === el) return i;
            return -1;
        };
    }

    //过滤字符串前后空格
    if (!String.prototype.trim) {
        String.prototype.trim = function () {
            return this.replace(/(^\s*)|(\s*$)/g, "");
        }
    }

    //过滤字符串前导空格
    if (!String.prototype.ltrim) {
        String.prototype.ltrim = function () {
            return this.replace(/(^\s*)/g, "");
        }
    }

    //过滤字符串结尾空格
    if (!String.prototype.rtrim) {
        String.prototype.rtrim = function () {
            return this.replace(/(\s*$)/g, "");
        }
    }

    /**
    * 浏览器信息
    **/
    var BrowserType = function () {
        var ua = navigator.userAgent.toLowerCase();
        var s;
        var bt = {};
        (s = ua.match(/msie ([\d.]+)/)) ? bt.ie = s[1] :
        (s = ua.match(/firefox\/([\d.]+)/)) ? bt.firefox = s[1] :
        (s = ua.match(/chrome\/([\d.]+)/)) ? bt.chrome = s[1] :
        (s = ua.match(/opera.([\d.]+)/)) ? bt.opera = s[1] :
        (s = ua.match(/version\/([\d.]+).*safari/)) ? bt.safari = s[1] : 0;

        /**
        * 客气端信息
        **/
        this.info = navigator.userAgent;

        /**
        * 如果为IE浏览器则此值为非0，指示浏览器版本
        **/
        this.ie = bt.ie;

        /**
        * 如果为火狐浏览器则此值为非0，指示浏览器版本
        **/
        this.firefox = bt.firefox;

        /**
        * 如果为Chrome浏览器则此值为非0，指示浏览器版本
        **/
        this.chrome = bt.chrome;

        /**
        * 如果为Opera浏览器则此值为非0，指示浏览器版本
        **/
        this.opera = bt.opera;

        /**
        * 如果为Safari浏览器则此值为非0，指示浏览器版本
        **/
        this.safari = bt.safari;

        /**
        * 检测浏览器版本,此方法只能检测主版本号和副版本号。如：检测IE浏览器是否为9.0，checkVersion("ie",9.0);
        * @param type 浏览器类型：ie/firefox/chrome/opera/safari
        * @param version 需要检测版本号，为浮点类型。
        * @param < 0 低于指定版本  0 与指定版本相同 > 0 高于指定版本 , Number.MAX_VALUE 非指定类型浏览器
        **/
        this.checkVersion = function (type, version) {
            if (this[type]) {
                var re = /(\d+(\.\d+)?)/;
                re.test(this[type]);
                var curVersion = parseFloat(RegExp.$1);
                return curVersion - version;
            }
            return Number.MAX_VALUE;
        };
    };

    /**
    * JFocus主框架类
    **/
    var JFocus = function () {
    };

    //类型
    JFocus.type = new Object();

    //应用程序对象
    JFocus.application = null;

    /**
    * 继承类型
    * @param subClass 子类型
    * @param superClass 父类型
    **/
    JFocus.inherited = function (subClass, superClass) {
        subClass.prototype = new superClass();
    };

    /**
    * 浏览器信息
    **/
    JFocus.browser = new BrowserType();

    /**
    * 初始化框架
    * @param frameRate 动画帧速（帧/秒）
    * @return 应用程序对象
    **/
    JFocus.startup = function (frameRate) {
        _startupTime = new Date().getTime();
        JFocus.application = new Application(frameRate);
        return JFocus.application;
    };

    /**
    * 创建一个精灵对象
    * @return 精灵对象
    **/
    JFocus.sprite = function (name) {
        return new JFocus.type.Sprite(name);
    };

    /**
    * 创建一个图片对象
    * @return 图片对象
    **/
    JFocus.image = function (name, url) {
        return new JFocus.type.Image(name, url);
    };

    /**
    * 获取应用运行时间
    * @return 运行时间（毫秒）
    **/
    JFocus.getTimer = function () {
        return new Date().getTime() - _startupTime;
    };

    ///Region:Struct & Contants

    /**
    * 点数据结构
    * @param x 横坐标
    * @param y 纵坐标
    **/
    JFocus.type.Point = function (x, y) {

        //横坐标
        this.x = 0;
        if (x != null) {
            this.x = x;
        };

        //纵坐标
        this.y = 0;
        if (y != null) {
            this.y = y;
        };

        /**
        * @inheritDoc
        * 返回字符串
        **/
        this.toString = function () {
            return "(" + this.x + "," + this.y + ")";
        };
    };

    ///Region:Event

    /**
    * 事件信息类型
    * @param type 事件类型
    **/
    JFocus.type.Event = function (type) {

        //事件类型
        this.type = type;

        //捕获事件目标
        this.target;

        /**
        * @inheritDoc
        * 返回字符串
        **/
        this.toString = function () {
            return "[Event " + this.type + "]";
        };
    };

    /**
    * 加载事件
    **/
    JFocus.type.Event.LOAD = "load";

    /**
    * 卸载事件
    **/
    JFocus.type.Event.UNLOAD = "unload";

    /**
    * 进入帧事件
    **/
    JFocus.type.Event.ENTER_FRAME = "enterFrame";

    /**
    * 初始化事件
    **/
    JFocus.type.Event.INIT = "init";

    /**
    * 变更事件
    **/
    JFocus.type.Event.CHANGE = "change";

    /**
    * 完成事件
    **/
    JFocus.type.Event.COMPLETE = "complete";

    /**
    * 取消事件
    **/
    JFocus.type.Event.CANCEL = "cancel";

    /**
    * 关闭事件
    **/
    JFocus.type.Event.CLOSE = "close";

    /**
    * 尺寸变更
    **/
    JFocus.type.Event.RESIZE = "resize";

    /**
    * 鼠标事件信息类
    * @param type 事件类型
    **/
    JFocus.type.MouseEvent = function (type) {
        JFocus.type.Event.apply(this, [type]);

        //鼠标处于当前对象的横坐标
        this.localX;

        //鼠标处于当前对象的纵坐标
        this.localY;

        //鼠标在场景中的横坐标
        this.stageX;

        //鼠标在场景中的纵坐标
        this.stageY;

        /**
        * @inheritDoc
        * 返回字符串
        **/
        this.toString = function () {
            return "[MouseEvent " + this.type + "]";
        };
    };
    JFocus.inherited(JFocus.type.MouseEvent, JFocus.type.Event);

    /**
    * 点击事件
    **/
    JFocus.type.MouseEvent.CLICK = "click";

    /**
    * 鼠标移出
    **/
    JFocus.type.MouseEvent.ROLL_OUT = "rollOut";

    /**
    * 鼠标移入
    **/
    JFocus.type.MouseEvent.ROLL_OVER = "rollOver";

    /**
    * 鼠标松开
    **/
    JFocus.type.MouseEvent.MOUSE_UP = "mouseUp";

    /**
    * 鼠标按下
    **/
    JFocus.type.MouseEvent.MOUSE_DOWN = "mouseDown";

    /**
    * 鼠标移动
    **/
    JFocus.type.MouseEvent.MOUSE_MOVE = "mouseMove";

    /**
    * 键盘事件信息类型
    * @param type 事件类型
    **/
    JFocus.type.KeyboardEvent = function (type) {
        JFocus.type.Event.apply(this, [type]);

        //按键编码
        this.keyCode;

        //是否按下shift键
        this.shiftKey;

        //是否按下ctrl键
        this.ctrlKey;

        //是否按下alt键
        this.altKey;

        /**
        * @inheritDoc
        * 返回字符串
        **/
        this.toString = function () {
            return "[KeyboardEvent " + this.type + "]";
        };
    };
    JFocus.inherited(JFocus.type.KeyboardEvent, JFocus.type.Event);

    /**
    * 按键按下
    **/
    JFocus.type.KeyboardEvent.KEY_DOWN = "keyDown";

    /**
    * 按键按压
    **/
    JFocus.type.KeyboardEvent.KEY_PRESS = "keyPress";

    /**
    * 按键松开
    **/
    JFocus.type.KeyboardEvent.KEY_UP = "keyUp";

    /**
    * 错误事件
    **/
    JFocus.type.ErrorEvent = function (type) {
        JFocus.type.Event.apply(this, [type]);

        //错误描述
        this.message;
    };
    JFocus.inherited(JFocus.type.ErrorEvent, JFocus.type.Event);

    /**
    * 错误
    **/
    JFocus.type.ErrorEvent.ERROR = "error";

    /**
    * 进度事件
    **/
    JFocus.type.ProgressEvent = function (type) {
        JFocus.type.Event.apply(this, [type]);

        this.loadedBytes = 0;
        this.totalBytes = 0;
    };
    JFocus.inherited(JFocus.type.ProgressEvent, JFocus.type.Event);

    /**
    * 进度
    **/
    JFocus.type.ProgressEvent.PROGRESS = "progress";

    ///Region:Core

    /**
    * 键盘管理器
    **/
    var KeyboardManager = function () {
        this._typeDict = new Object();

        var self = this;

        /**
        * 按键按下事件处理
        * @param event 事件对象
        **/
        this._keyDownHandler = function (event) {
            var type = JFocus.type.KeyboardEvent.KEY_DOWN;
            if (self._typeDict[type] != null) {
                //派发事件
                for (var i = 0; i < self._typeDict[type].length; i++) {
                    var itemObj = self._typeDict[type][i];
                    itemObj.listener.apply(itemObj.observer, [event]);
                }
            }
        };

        /**
        * 按键松开事件处理
        * @param event 事件对象
        **/
        this._keyUpHandler = function (event) {
            var type = JFocus.type.KeyboardEvent.KEY_UP;
            if (self._typeDict[type] != null) {
                //派发事件
                for (var i = 0; i < self._typeDict[type].length; i++) {
                    var itemObj = self._typeDict[type][i];
                    itemObj.listener.apply(itemObj.observer, [event]);
                }
            }
        };

        /**
        * 按键按压事件处理
        * @param event 事件对象
        **/
        this._keyPressHandler = function (event) {
            var type = JFocus.type.KeyboardEvent.KEY_PRESS;
            if (this._typeDict[type] != null) {
                //派发事件
                for (var i = 0; i < this._typeDict[type].length; i++) {
                    var itemObj = this._typeDict[type][i];
                    itemObj.listener.apply(itemObj.observer, [event]);
                }
            }
        };

        if (JFocus.browser.ie && JFocus.browser.checkVersion("ie", 9)) {

            /**
            * 添加监听器
            * @param type 事件类型
            * @param observer 观察事件对象
            * @param listener 监听器事件
            **/
            this.addListener = function (type, observer, listener) {
                if (this._typeDict[type] == null) {
                    this._typeDict[type] = new Array();

                    switch (type) {
                        case JFocus.type.KeyboardEvent.KEY_DOWN:
                            document.onkeydown = this._keyDownHandler;
                            break;
                        case JFocus.type.KeyboardEvent.KEY_UP:
                            document.onkeyup = this._keyUpHandler;
                            break;
                        case JFocus.type.KeyboardEvent.KEY_PRESS:
                            document.onkeypress = this._keyPressHandler;
                            break;
                    }
                }

                var hasExists = false;
                for (var i = 0; i < this._typeDict[type].length; i++) {
                    var itemObj = this._typeDict[type][i];
                    if (itemObj.observer == observer && itemObj.listener == listener) {
                        hasExists = true;
                        break;
                    }
                }

                if (!hasExists) {
                    this._typeDict[type].push({ observer: observer, listener: listener });
                }
            };

            /**
            * 移除监听器
            * @param type 事件类型
            * @param observer 观察事件对象
            * @param listener 监听器事件
            **/
            this.removeListener = function (type, observer, listener) {
                if (this._typeDict[type] != null) {
                    for (var i = 0; i < this._typeDict[type].length; i++) {
                        var itemObj = this._typeDict[type][i];
                        if (itemObj.observer == observer && itemObj.listener == listener) {
                            this._typeDict[type].splice(i, 1);
                            break;
                        }
                    }

                    if (this._typeDict[type].length == 0) {
                        switch (type) {
                            case JFocus.type.KeyboardEvent.KEY_DOWN:
                                document.onkeydown = null;
                                break;
                            case JFocus.type.KeyboardEvent.KEY_UP:
                                document.onkeyup = null;
                                break;
                            case JFocus.type.KeyboardEvent.KEY_PRESS:
                                document.onkeypress = null;
                                break;
                        }
                    }
                }
            };

        } else {

            /**
            * 添加监听器
            * @param type 事件类型
            * @param observer 观察事件对象
            * @param listener 监听器事件
            **/
            this.addListener = function (type, observer, listener) {
                if (this._typeDict[type] == null) {
                    this._typeDict[type] = new Array();

                    switch (type) {
                        case JFocus.type.KeyboardEvent.KEY_DOWN:
                            window.onkeydown = this._keyDownHandler;
                            break;
                        case JFocus.type.KeyboardEvent.KEY_UP:
                            window.onkeyup = this._keyUpHandler;
                            break;
                        case JFocus.type.KeyboardEvent.KEY_PRESS:
                            window.onkeypress = this._keyPressHandler;
                            break;
                    }
                }

                var hasExists = false;
                for (var i = 0; i < this._typeDict[type].length; i++) {
                    var itemObj = this._typeDict[type][i];
                    if (itemObj.observer == observer && itemObj.listener == listener) {
                        hasExists = true;
                        break;
                    }
                }

                if (!hasExists) {
                    this._typeDict[type].push({ observer: observer, listener: listener });
                }
            };

            /**
            * 移除监听器
            * @param type 事件类型
            * @param observer 观察事件对象
            * @param listener 监听器事件
            **/
            this.removeListener = function (type, observer, listener) {
                if (this._typeDict[type] != null) {
                    for (var i = 0; i < this._typeDict[type].length; i++) {
                        var itemObj = this._typeDict[type][i];
                        if (itemObj.observer == observer && itemObj.listener == listener) {
                            this._typeDict[type].splice(i, 1);
                            break;
                        }
                    }

                    if (this._typeDict[type].length == 0) {
                        switch (type) {
                            case JFocus.type.KeyboardEvent.KEY_DOWN:
                                window.onkeydown = null;
                                break;
                            case JFocus.type.KeyboardEvent.KEY_UP:
                                window.onkeyup = null;
                                break;
                            case JFocus.type.KeyboardEvent.KEY_PRESS:
                                window.onkeypress = null;
                                break;
                        }
                    }
                }
            };
        }



        /**
        * @inheritDoc
        * 返回字符串
        **/
        this.toString = function () {
            return "[KeyboardManager manager]";
        };
    };
    JFocus.keyboardManager = new KeyboardManager();

    /**
    * 事件派发器
    * @param target 事件派发器目标对象，如果不指定则为派发器自身 
    **/
    JFocus.type.EventDispatcher = function (target) {
        this._target = target;
        if (this._target == null) {
            this._target = this;
        }
        this._observers = new Object();

        /**
        * 判断是否包含指定事件的监听器
        * @param type 事件类型
        * @param listener 事件监听器，如果为null则不判断指定监听器
        * @return true表示存在监听器，否则没有。
        **/
        this.hasEventListener = function (type, listener) {
            if (this._observers[type] != null) {
                if (listener != null) {
                    //如果指定了监听器则检测监听器
                    for (var i = 0; i < this._observers[type].length; i++) {
                        var item = this._observers[type][i];
                        if (item.listener == listener) {
                            return true;
                        }
                    }
                } else {
                    return this._observers[type].length > 0 ? true : false;
                }
            }
            return false;
        };

        /**
        * 添加事件处理器
        * @param type 事件类型
        * @param listener 监听器
        * @param target 监听器对象，表示监听器所属对象，如果不指定则可能会导致this指向不正确，在不使用this的情况下可以设置为null
        **/
        this.addEventListener = function (type, listener, target) {
            if (this._observers[type] == null) {
                this._observers[type] = new Array();
            }

            if (!this.hasEventListener(type, listener)) {
                this._observers[type].push({ listener: listener, target: target });
            }
        };

        /**
        * 删除事件处理器
        * @param type 事件类型
        * @param listener 监听器
        **/
        this.removeEventListener = function (type, listener) {
            if (this._observers[type] != null) {
                for (var i = 0; i < this._observers[type].length; i++) {
                    var item = this._observers[type][i];
                    if (item.listener == listener) {
                        this._observers[type].splice(i, 1);
                        break;
                    }
                }
            }
        };

        /**
        * 派发事件
        * event 事件对象
        **/
        this.dispatchEvent = function (event) {
            var type = event.type;
            if (this._observers[type] != null) {
                event.target = this._target;
                for (var i = 0; i < this._observers[type].length; i++) {
                    var item = this._observers[type][i];
                    if (item.target == null) {
                        item.listener(event);
                    } else {
                        item.listener.apply(item.target, [event]);
                    }
                }
            }
        };

        /**
        * @inheritDoc
        * 返回字符串
        **/
        this.toString = function () {
            return "[EventDispatcher dispatcher]";
        };
    };

    ///Region:Display

    /**
    * 可视化对象属性状态,用于监控对象属性状态。
    **/
    var DisplayObjectPropertyManager = function (displayObject, propertys) {
        var _states = {};
        var _target = displayObject;

        /**
        * 初始化属性
        * @param propertys 属性集合
        **/
        this.initProperty = function (propertys) {
            //初始化属性
            for (var i in propertys) {
                _target[i] = propertys[i];
                _states[i] = propertys[i];
            }
        };

        /**
        * 属性值变更
        * @param propName 属性名称
        * @param newValue 新属性值
        * @return true 表示值变更，否则证明值相同，没有变更。
        **/
        this.changeValue = function (propName, newValue) {
            if (_target[propName] != newValue) {
                _states[propName] = _target[propName];
                _target[propName] = newValue;
                return true;
            }
            return false;
        };

        /**
        * 获取属性值
        * @param propName 属性名称
        * @return 属性值
        **/
        this.getValue = function (propName) {
            return _target[propName];
        };

        /**
        * 获取旧属性值
        * @param propName 属性名称
        * @return 属性值
        **/
        this.getOldValue = function (propName) {
            return _states[propName];
        };

        /**
        * 同步属性值,刷新某个属性值与新值相同
        * @param propName 属性名称
        **/
        this.syncValue = function (propName) {
            _states[propName] = _target[propName];
        };

        /**
        * 判断属性值是否发生变更
        * @return true 表示发生变更，否则无变更
        **/
        this.hasChanged = function (propName) {
            return _states[propName] == _target[propName] ? false : true;
        };

        /**
        * 销毁对象
        **/
        this.destory = function () {
            for (var i in _states) {
                delete _states[i];
                delete _target[i];
            }
        };

        //初始话属性
        this.initProperty(propertys);
    };

    /**
    * 可视化对象类
    * @param name 对象ID
    **/
    JFocus.type.DisplayObject = function (name) {
        JFocus.type.EventDispatcher.apply(this, [null]);

        //属性管理器
        this._propertyManager = new DisplayObjectPropertyManager(this, {
            _x: 0,
            _y: 0,
            _width: 0,
            _height: 0,
            _alpha: 100,
            _rotation: 0,
            _visible: true,
            _mask: null,
            _name: name,
            _visible: true
        });

        this._handle = null;        //对象句柄
        this.root = null; 			//对象的根显示对象，如果为null则表示尚未加入到顶级显示列表
        this.parent = null; 		//对象的父级容器
        this._hasRedraw = true; 	//重绘标识，true表示下一周期需要进行重绘

        //根据名称获取对象
        if (name != null) {
            this._handle = document.getElementById(name);
        }

        /**
        * 重绘组件
        **/
        this._redraw = function () {
        };

        /**
        * 对象样式
        * @param name 样式名称
        * @param value 样式值,如果不传入此参数则表示获取样式值
        **/
        this.style = function (name, value) {
            switch (arguments.length) {
                case 1:
                    return this._handle.style[name];
                case 2:
                    this._handle.style[name] = value;
                    break;
            }
        };

        /**
        * 设置/获取样式类
        * @param 类名称
        **/
        this.cssClass = function (value) {
            if (arguments.length > 0) {
                this._handle.className = value;
            } else {
                return this._handle.className;
            }
        }

        /**
        * 顶点横坐标
        * @param value 坐标值，不传入此参数则表示获取横坐标值
        **/
        this.x = function (value) {
            if (arguments.length > 0) {
                if (this._propertyManager.changeValue("_x", value)) {
                    this.invalidate();
                }
            } else {
                return this._propertyManager.getValue("_x");
            }
        };

        /**
        * 顶点纵坐标
        * @param value 坐标值，不传入此参数则表示获取纵坐标值
        **/
        this.y = function (value) {
            if (arguments.length > 0) {
                if (this._propertyManager.changeValue("_y", value)) {
                    this.invalidate();
                }
            } else {
                return this._propertyManager.getValue("_y");
            }
        };

        /**
        * 宽度
        * @param value 宽度，不传入此参数则表示获取宽度
        **/
        this.width = function (value) {
            if (arguments.length > 0) {
                if (this._propertyManager.changeValue("_width", value)) {
                    this.invalidate();
                }
            } else {
                return this._propertyManager.getValue("_width");
            }
        };

        /**
        * 高度
        * @param value 高度，不传入此参数则表示获取高度
        **/
        this.height = function (value) {
            if (arguments.length > 0) {
                if (this._propertyManager.changeValue("_height", value)) {
                    this.invalidate();
                }
            } else {
                return this._propertyManager.getValue("_height");
            }
        };

        /**
        * 对象名称,只读属性
        **/
        this.name = function () {
            return this._propertyManager.getValue("_name");
        };

        /**
        * 遮罩
        * @param value 遮罩对象，如果不传入此参数则表示获取遮罩对象
        **/
        this.mask = function (value) {
            if (arguments.length > 0) {
                if ((value instanceof JFocus.type.MaskLayer) && this._propertyManager.changeValue("_mask", value)) {
                    var maskObj = this._propertyManager.getValue("_mask");
                    if (maskObj != null) {
                        maskObj.maskTarget(this);
                    }
                    this.invalidate();
                }
            } else {
                return this._mask;
            }
        };

        /**
        * 透明度
        * @param value 透明度，不传入此参数则表示获取透明度
        **/
        this.alpha = function (value) {
            if (arguments.length > 0) {
                if (this._propertyManager.changeValue("_alpha", value)) {
                    this.invalidate();
                }
            } else {
                return this._propertyManager.getValue("_alpha");
            }
        };

        /**
        * 旋转
        * @param value 角度值，不传入此参数则表示获取旋转角度。
        **/
        this.rotation = function (value) {
            if (arguments.length > 0) {
                if (this._propertyManager.changeValue("_rotation", value)) {
                    this.invalidate();
                }
            } else {
                return this._propertyManager.getValue("_rotation");
            }
        };

        /**
        * 对象可视标识
        * @param value 可视标识，true表示显示，false表示隐藏。不传入此参数则表示获取可视标识。
        **/
        this.visible = function (value) {
            if (arguments.length > 0) {
                if (this._propertyManager.changeValue("_visible", value)) {
                    this.invalidate();
                }
            } else {
                return this._propertyManager.getValue("_visible");
            }
        };

        /**
        * 鼠标位置的横坐标
        **/
        this.mouseX = function () {
            if (this.root == null) {
                return 0;
            }
            return this._xGlobalToLocal(this.root.mouseX());
        };

        /**
        * 鼠标位置的纵坐标
        **/
        this.mouseY = function () {
            if (this.root == null) {
                return 0;
            }
            return this._yGlobalToLocal(this.root.mouseY());
        };

        /**
        * 激活控件刷新，在下一个刷新周期中将会执行
        **/
        this.invalidate = function () {
            this._hasRedraw = true;

            if (this.root != null) {
                //触发应用程序刷新
                this.root.invalidate();
            }
        };

        /**
        * 当前横坐标值转换为全局坐标值
        * @param x 横坐标值
        * @return 全局横坐标值
        **/
        this._xLocalToGlobal = function (x) {
            var tmp = x;

            var curDisplayObject = this;
            while (curDisplayObject != null && curDisplayObject != this.root) {
                tmp += curDisplayObject.x();

                curDisplayObject = curDisplayObject.parent;
            }

            return tmp;
        };

        /**
        * 当前纵坐标值转换为全局坐标值
        * @param x 纵坐标值
        * @return 全局纵坐标值
        **/
        this._yLocalToGlobal = function (y) {
            var tmp = y;

            var curDisplayObject = this;
            while (curDisplayObject != null && curDisplayObject != this.root) {
                tmp += curDisplayObject.y();

                curDisplayObject = curDisplayObject.parent;
            }

            return tmp;
        };

        /**
        * 全局横坐标值转换为当前坐标值
        * @param x 横坐标值
        * @return 当前横坐标值
        **/
        this._xGlobalToLocal = function (x) {
            var tmp = x;

            var curDisplayObject = this;
            while (curDisplayObject != null && curDisplayObject != this.root) {
                tmp -= curDisplayObject.x();

                curDisplayObject = curDisplayObject.parent;
            }

            return tmp;
        };

        /**
        * 全局纵坐标值转换为当前坐标值
        * @param x 纵坐标值
        * @return 当前纵坐标值
        **/
        this._yGlobalToLocal = function (y) {
            var tmp = y;

            var curDisplayObject = this;
            while (curDisplayObject != null && curDisplayObject != this.root) {
                tmp -= curDisplayObject.y();

                curDisplayObject = curDisplayObject.parent;
            }

            return tmp;
        };

        /**
        * 转换当前坐标为全局坐标点
        * @param point 当前坐标点
        * @return 全局坐标点
        **/
        this.localToGlobal = function (point) {
            if (point instanceof JFocus.type.Point) {
                var x = point.x;
                var y = point.y;

                var curDisplayObject = this;
                while (curDisplayObject != null && curDisplayObject != this.root) {
                    x += curDisplayObject.x();
                    y += curDisplayObject.y();

                    curDisplayObject = curDisplayObject.parent;
                }

                return new JFocus.type.Point(x, y);
            }
            return new JFocus.type.Point();
        };

        /**
        * 转换全局坐标为当前坐标点
        * @param point 全局坐标点
        * @return 当前坐标点
        **/
        this.globalToLocal = function (point) {
            if (point instanceof JFocus.type.Point) {
                var x = point.x;
                var y = point.y;

                var curDisplayObject = this.parent;
                while (curDisplayObject != null && curDisplayObject != this.root) {
                    x -= curDisplayObject.x();
                    y -= curDisplayObject.y();

                    curDisplayObject = curDisplayObject.parent;
                }

                return new JFocus.type.Point(x, y);
            }
            return new JFocus.type.Point();
        };

        /**
        * @inheritDoc
        * 返回字符串
        **/
        this.toString = function () {
            return "[DisplayObject " + this._name + "]";
        };
    };
    JFocus.inherited(JFocus.type.DisplayObject, JFocus.type.EventDispatcher);

    /**
    * 可视化对象容器
    **/
    JFocus.type.DisplayObjectContainer = function (name) {
        JFocus.type.DisplayObject.apply(this, [name]);

        this._propertyManager.initProperty({ _contentSelectable: true });
        this._displayList = new Array();

        //判断是否已经在文档存在
        if (this._handle == null || this._handle.tagName != "DIV") {
            this._handle = document.createElement("div");
            this._handle.id = this.name();
            this._handle.name = this.name();
        }
        if (JFocus.browser.ie && JFocus.browser.checkVersion("ie", 8) < 0) {
            this._clipDefaultValue = this._handle.style.clip;
        } else {
            this._clipDefaultValue = "auto";
        }
        this._handle.style.position = "absolute";
        //使容器无法拖曳
        this._handle.ondragstart = function () {
            return false;
        };

        if (JFocus.browser.ie) {
            //IE浏览器使用滤镜进行旋转
            this._drawRotationAndFrameFunc = function () {
                if (this._propertyManager.hasChanged("_rotation")) {
                    this._propertyManager.syncValue("_rotation");

                    var rad = this.rotation() * (Math.PI / 180);
                    var cosValue = Math.cos(rad);
                    var sinValue = Math.sin(rad);
                    //原始中心点
                    var srcCX = this.width() / 2;
                    var srcCY = this.height() / 2;

                    this._handle.style.filter = "progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand', M11=" + cosValue + ", M12=" + (-sinValue) + ", M21=" + sinValue + ", M22=" + cosValue + ")";

                    //转换后中心点
                    rect = this._handle.getBoundingClientRect();
                    var cx = (rect.right - rect.left) / 2;
                    var cy = (rect.bottom - rect.top) / 2;

                    this._handle.style.left = (this.x() + srcCX - cx) + "px";
                    this._handle.style.top = (this.y() + srcCY - cy) + "px";
                    this._handle.style.width = this.width() + "px";
                    this._handle.style.height = this.height() + "px";
                } else {
                    this._handle.style.left = this.x() + "px";
                    this._handle.style.top = this.y() + "px";
                    this._handle.style.width = this.width() + "px";
                    this._handle.style.height = this.height() + "px";
                }
            };

        } else {

            this._drawRotationAndFrameFunc = function () {
                this._handle.style.left = this.x() + "px";
                this._handle.style.top = this.y() + "px";
                this._handle.style.width = this.width() + "px";
                this._handle.style.height = this.height() + "px";

                if (this._propertyManager.hasChanged("_rotation")) {
                    this._propertyManager.syncValue("_rotation");
                    this._handle.style.OTransform = " rotate(" + this.rotation() + "deg)"; 	//Opera
                    this._handle.style.WebkitTransform = " rotate(" + this.rotation() + "deg)"; //Webkit核心
                    this._handle.style.MozTransform = " rotate(" + this.rotation() + "deg)"; 	//火狐
                    this._handle.style.Transform = "rotate(" + this.rotation() + "deg)";
                }
            };
        }

        /**
        * 重绘对象
        **/
        this._redraw = function () {
            if (this._hasRedraw && this._handle != null) {
                this._drawRect();
                this._hasRedraw = false;
            }
            //重绘子对象
            for (var i = 0; i < this._displayList.length; i++) {
                var displayObj = this._displayList[i];
                displayObj.root = this.root;
                displayObj.parent = this;
                displayObj._redraw();
            }
        };

        /**
        * 绘画对象
        **/
        this._drawRect = function () {
            if (this.visible()) {
                this._handle.style.display = "block";

                this._drawRotationAndFrameFunc();

                if (this._propertyManager.hasChanged("_alpha")) {
                    this._propertyManager.syncValue("_alpha");

                    this._handle.style.filter = "Alpha(Opacity=" + this.alpha() + ")"; //IE中设置透明
                    this._handle.style.MozOpacity = this.alpha() / 100; 			//火狐
                    this._handle.style.opacity = this.alpha() / 100; 				//Webkit核心
                }

                //绘画遮罩
                var maskObj = this.mask();
                //判断是否有遮罩层
                if (maskObj != null) {
                    //计算遮罩范围
                    var left = Math.max(this.x(), maskObj.x());
                    var right = Math.min(this.x() + this.width(), maskObj.x() + maskObj.width());
                    var top = Math.max(this.y(), maskObj.y());
                    var bottom = Math.min(this.y() + this.height(), maskObj.y() + maskObj.height());

                    if (left < right && top < bottom) {
                        top -= this._y;
                        bottom -= this._y;
                        left -= this._x;
                        right -= this._x;
                        this._handle.style.clip = "rect(" + top + "px " + right + "px " + bottom + "px " + left + "px)";
                        this._handle.style.clip = "rect(" + top + "px, " + right + "px, " + bottom + "px, " + left + "px)";
                    } else {
                        this._handle.style.clip = "rect(0px 0px 0px 0px)";
                        this._handle.style.clip = "rect(0px, 0px, 0px, 0px)";
                    }
                } else {
                    this._handle.style.clip = this._clipDefaultValue;
                }
            } else {
                this._handle.style.display = "none";
            }
        };

        /**
        * 选择开始事件，不允许选择内容时触发。
        **/
        this._selectStartHandler = function (event) {
            return false;
        };

        /**
        * 添加子对象
        * @param child 子对象
        **/
        this.addChild = function (child) {
            if (child instanceof JFocus.type.DisplayObject) {
                //加入显示队列
                this._displayList.push(child);
                this._handle.appendChild(child._handle);
                this.invalidate();
            }
        };

        /**
        * 移除子对象
        * @param child 子对象
        **/
        this.removeChild = function (child) {
            if (child instanceof JFocus.type.DisplayObject) {
                //从显示队列移除
                var pos = this._displayList.indexOf(child);
                if (pos > -1) {
                    this._displayList.splice(pos, 1);
                    this._handle.removeChild(child._handle);
                }
                this.invalidate();
            }
        };

        /**
        * 移除所有子对象
        **/
        this.removeAllChild = function () {
            for (var i = 0; i < this._displayList.length; i++) {
                this._handle.removeChild(this._displayList[i]._handle);
            }
            this._displayList.splice(0);
            this.invalidate();
        };

        /**
        * 是否包含对象
        * @return true表示包含对象，否则不包含
        **/
        this.contains = function (child) {
            return this._displayList.indexOf(child) > -1 ? true : false;
        };

        /**
        * 内容可选标识
        **/
        this.contentSelectable = function (value) {
            if (arguments.length > 0) {
                if (this._propertyManager.changeValue("_contentSelectable", value)) {
                    if (this._propertyManager.getValue("_contentSelectable")) {
                        this._handle.onselectstart = null;
                    } else {
                        this._handle.onselectstart = this._selectStartHandler;
                    }
                }
            } else {
                return this._propertyManager.getValue("_contentSelectable");
            }
        };
    };
    JFocus.inherited(JFocus.type.DisplayObjectContainer, JFocus.type.DisplayObject);

    /**
    * 应用程序类
    * @param frameRate 帧速
    **/
    var Application = function (frameRate) {
        JFocus.type.DisplayObjectContainer.apply(this, ["application"]);

        this._handle = document.getElementsByTagName("body")[0];
        this._propertyManager.initProperty({
            _frameRate: 1000 / frameRate,
            _mouseX: 0,
            _mouseY: 0
        });
        var self = this;

        /**
        * 改写重绘方法
        **/
        this._redraw = function () {
            if (this._hasRedraw && this._handle != null) {
                //重绘子对象
                for (var i = 0; i < this._displayList.length; i++) {
                    var displayObj = this._displayList[i];
                    displayObj.root = this;
                    displayObj.parent = this;
                    displayObj._redraw();
                }
                this._hasRedraw = false;
            }
        };


        /**
        * 加载事件
        * @param event 事件对象
        **/
        this._loadHandler = function (event) {
            event = event ? event : window.event;
            var e = new JFocus.type.Event(JFocus.type.Event.LOAD);
            self.dispatchEvent(e);

            setInterval("__mainRunLoop();", self._propertyManager.getValue("_frameRate"));
        };

        /**
        * 卸载事件
        * @param event 事件对象
        **/
        this._unloadHandler = function (event) {
            event = event ? event : window.event;
            var e = new JFocus.type.Event(JFocus.type.Event.UNLOAD);
            self.dispatchEvent(e);
        };

        /**
        * 自动拉伸事件
        * @param event 事件对象
        **/
        this._resizeHandler = function (event) {
            event = event ? event : window.event;
            var e = new JFocus.type.Event(JFocus.type.Event.RESIZE);
            self.dispatchEvent(e);
        };

        /**
        * 鼠标移动事件
        * @param event 事件对象
        **/
        this._mouseMoveHandler = function (event) {
            event = event ? event : window.event;
            self._propertyManager.changeValue("_mouseX", event.clientX);
            self._propertyManager.changeValue("_mouseY", event.clientY);

            var e = new JFocus.type.MouseEvent(JFocus.type.MouseEvent.MOUSE_MOVE);
            e.localX = event.layerX;
            e.localY = event.layerY;
            e.stageX = event.clientX;
            e.stageY = event.clientY;
            self.dispatchEvent(e);
        };

        /**
        * @inheritDoc
        **/
        this.addEventListener = function (type, listener, target) {
            Application.prototype.addEventListener.apply(this, [type, listener, target]);

            //根据类型判断监听事件处理器
            switch (type) {
                case JFocus.type.MouseEvent.CLICK:
                    window.onclick = this._clickHandler;
                    break;
                case JFocus.type.MouseEvent.MOUSE_UP:
                    if (JFocus.browser.ie) {
                        document.onmouseup = this._mouseUpHandler;
                    } else {
                        window.onmouseup = this._mouseUpHandler;
                    }
                    break;
                case JFocus.type.MouseEvent.MOUSE_DOWN:
                    if (JFocus.browser.ie) {
                        document.onmousedown = this._mouseDownHandler;
                    } else {
                        window.onmousedown = this._mouseDownHandler;
                    }
                    break;
                case JFocus.type.MouseEvent.ROLL_OVER:
                    window.onmouseover = this._rollOverHandler;
                    break;
                case JFocus.type.MouseEvent.ROLL_OUT:
                    window.onmouseout = this._rollOutHandler;
                    break;
                case JFocus.type.KeyboardEvent.KEY_DOWN:
                    JFocus.keyboardManager.addListener(JFocus.type.KeyboardEvent.KEY_DOWN, this, this._keyDownHandler);
                    break;
                case JFocus.type.KeyboardEvent.KEY_UP:
                    JFocus.keyboardManager.addListener(JFocus.type.KeyboardEvent.KEY_UP, this, this._keyUpHandler);
                    break;
                case JFocus.type.KeyboardEvent.KEY_PRESS:
                    JFocus.keyboardManager.addListener(JFocus.type.KeyboardEvent.KEY_PRESS, this, this._keyPressHandler);
                    break;
            }
        };

        /**
        * @inheritDoc
        **/
        this.removeEventListener = function (type, listener) {
            Application.prototype.removeEventListener.apply(this, [type, listener]);

            //根据类型判断移除事件处理器
            if (!this.hasEventListener(type)) {
                switch (type) {
                    case JFocus.type.MouseEvent.CLICK:
                        window.onclick = null;
                        break;
                    case JFocus.type.MouseEvent.MOUSE_UP:
                        if (JFocus.browser.ie) {
                            document.onmouseup = null;
                        } else {
                            window.onmouseup = null;
                        }
                        break;
                    case JFocus.type.MouseEvent.MOUSE_DOWN:
                        if (JFocus.browser.ie) {
                            document.onmousedown = null;
                        } else {
                            window.onmousedown = null;
                        }
                        break;
                    case JFocus.type.MouseEvent.ROLL_OVER:
                        window.onmouseover = null;
                        break;
                    case JFocus.type.MouseEvent.ROLL_OUT:
                        window.onmouseout = null;
                        break;
                    case JFocus.type.KeyboardEvent.KEY_DOWN:
                        JFocus.keyboardManager.removeListener(JFocus.type.KeyboardEvent.KEY_DOWN, this, this._keyDownHandler);
                        break;
                    case JFocus.type.KeyboardEvent.KEY_UP:
                        JFocus.keyboardManager.removeListener(JFocus.type.KeyboardEvent.KEY_UP, this, this._keyUpHandler);
                        break;
                    case JFocus.type.KeyboardEvent.KEY_PRESS:
                        JFocus.keyboardManager.removeListener(JFocus.type.KeyboardEvent.KEY_PRESS, this, this._keyPressHandler);
                        break;
                }
            }
        };

        /**
        * 鼠标点击
        * @param event 事件对象
        **/
        this._clickHandler = function (event) {
            event = event ? event : window.event;

            var e = new JFocus.type.MouseEvent(JFocus.type.MouseEvent.CLICK);
            e.localX = event.layerX;
            e.localY = event.layerY;
            e.stageX = event.clientX;
            e.stageY = event.clientY;
            self.dispatchEvent(e);
        };

        /**
        * 鼠标松开
        * @param event 事件对象
        **/
        this._mouseUpHandler = function (event) {
            event = event ? event : window.event;

            var e = new JFocus.type.MouseEvent(JFocus.type.MouseEvent.MOUSE_UP);
            e.localX = event.layerX;
            e.localY = event.layerY;
            e.stageX = event.clientX;
            e.stageY = event.clientY;
            self.dispatchEvent(e);
        };

        /**
        * 鼠标按下
        * @param event 事件对象
        **/
        this._mouseDownHandler = function (event) {
            event = event ? event : window.event;
            var e = new JFocus.type.MouseEvent(JFocus.type.MouseEvent.MOUSE_DOWN);
            e.localX = event.layerX;
            e.localY = event.layerY;
            e.stageX = event.clientX;
            e.stageY = event.clientY;
            self.dispatchEvent(e);
        };

        /**
        * 鼠标移入
        * @param event 事件对象
        **/
        this._rollOverHandler = function (event) {
            event = event ? event : window.event;

            var e = new JFocus.type.MouseEvent(JFocus.type.MouseEvent.ROLL_OVER);
            e.localX = event.layerX;
            e.localY = event.layerY;
            e.stageX = event.clientX;
            e.stageY = event.clientY;
            self.dispatchEvent(e);
        };

        /**
        * 鼠标移出
        * @param event 事件对象
        **/
        this._rollOutHandler = function (event) {
            event = event ? event : window.event;

            var e = new JFocus.type.MouseEvent(JFocus.type.MouseEvent.ROLL_OUT);
            e.localX = event.layerX;
            e.localY = event.layerY;
            e.stageX = event.clientX;
            e.stageY = event.clientY;
            self.dispatchEvent(e);
        };

        /**
        * 按键按下事件
        * @param event 事件对象
        **/
        this._keyDownHandler = function (event) {
            event = event ? event : window.event;

            var e = new JFocus.type.KeyboardEvent(JFocus.type.KeyboardEvent.KEY_DOWN);
            self.dispatchEvent(e);
        };

        /**
        * 按键松开事件
        * @param event 事件对象
        **/
        this._keyUpHandler = function (event) {
            event = event ? event : window.event;
            var e = new JFocus.type.KeyboardEvent(JFocus.type.KeyboardEvent.KEY_UP);
            self.dispatchEvent(e);
        };

        /**
        * 按键按压事件
        * @param event 事件对象
        **/
        this._keyPressHandler = function (event) {
            event = event ? event : window.event;
            var e = new JFocus.type.KeyboardEvent(JFocus.type.KeyboardEvent.KEY_PRESS);
            self.dispatchEvent(e);
        };

        /**
        * 触发下一刷新周期重绘
        * @param event 事件对象
        **/
        this.invalidate = function () {
            this._hasRedraw = true;
        };

        /**
        * 左上角横坐标
        **/
        this.x = function () {
            return 0;
        };

        /**
        * 左上角纵坐标
        **/
        this.y = function () {
            return 0;
        };

        /**
        * 获取场景宽度
        **/
        this.width = function () {
            return document.documentElement.clientWidth;
        };

        /**
        * 获取场景高度
        **/
        this.height = function () {
            return document.documentElement.clientHeight;
        };

        /**
        * 鼠标位置的横坐标
        **/
        this.mouseX = function () {
            return this._propertyManager.getValue("_mouseX");
        };

        /**
        * 鼠标位置的纵坐标
        **/
        this.mouseY = function () {
            return this._propertyManager.getValue("_mouseY");
        };

        this._handle.onload = this._loadHandler;
        this._handle.onresize = this._resizeHandler;

        if (JFocus.browser.ie) {
            document.onmousemove = this._mouseMoveHandler;
        } else {
            window.onmousemove = this._mouseMoveHandler;
        }
    };
    JFocus.inherited(Application, JFocus.type.DisplayObjectContainer);

    /**
    * 精灵类
    **/
    JFocus.type.Sprite = function (name) {
        JFocus.type.DisplayObjectContainer.apply(this, [name]);

        this._propertyManager.initProperty({ _mask: null,
            _offsetX: 0,
            _offsetY: 0,
            _canDrag: false,
            _dragCenter: false
        });
        var self = this;

        /**
        * @inheritDoc
        * 绘画对象
        **/
        this._drawRect = function () {
            JFocus.type.Sprite.prototype._drawRect.apply(this, []);

            if (this._propertyManager.getValue("_canDrag")) {
                this._propertyManager.changeValue("_canDrag", false);

                //进行拖动
                this._doDrag(this._propertyManager.getValue("_dragCenter"));
            }
        };

        /**
        * @inheritDoc
        **/
        this.addEventListener = function (type, listener, target) {
            JFocus.type.Sprite.prototype.addEventListener.apply(this, [type, listener, target]);

            //根据类型判断监听事件处理器
            switch (type) {
                case JFocus.type.MouseEvent.CLICK:
                    this._handle.onclick = this._clickHandler;
                    break;
                case JFocus.type.MouseEvent.MOUSE_UP:
                    this._handle.onmouseup = this._mouseUpHandler;
                    break;
                case JFocus.type.MouseEvent.MOUSE_DOWN:
                    this._handle.onmousedown = this._mouseDownHandler;
                    break;
                case JFocus.type.MouseEvent.MOUSE_MOVE:
                    this._handle.onmousemove = this._mouseMoveHandler;
                    break;
                case JFocus.type.MouseEvent.ROLL_OVER:
                    this._handle.onmouseover = this._rollOverHandler;
                    break;
                case JFocus.type.MouseEvent.ROLL_OUT:
                    this._handle.onmouseout = this._rollOutHandler;
                    break;
                case JFocus.type.KeyboardEvent.KEY_DOWN:
                    JFocus.keyboardManager.addListener(JFocus.type.KeyboardEvent.KEY_DOWN, this, this._keyDownHandler);
                    break;
                case JFocus.type.KeyboardEvent.KEY_UP:
                    JFocus.keyboardManager.addListener(JFocus.type.KeyboardEvent.KEY_UP, this, this._keyUpHandler);
                    break;
                case JFocus.type.KeyboardEvent.KEY_PRESS:
                    JFocus.keyboardManager.addListener(JFocus.type.KeyboardEvent.KEY_PRESS, this, this._keyPressHandler);
                    break;
            }
        };

        /**
        * @inheritDoc
        **/
        this.removeEventListener = function (type, listener) {
            JFocus.type.Sprite.prototype.removeEventListener.apply(this, [type, listener]);

            //根据类型判断移除事件处理器
            if (!this.hasEventListener(type)) {
                switch (type) {
                    case JFocus.type.MouseEvent.CLICK:
                        this._handle.onclick = null;
                        break;
                    case JFocus.type.MouseEvent.MOUSE_UP:
                        this._handle.onmouseup = null;
                        break;
                    case JFocus.type.MouseEvent.MOUSE_DOWN:
                        this._handle.onmousedown = null;
                        break;
                    case JFocus.type.MouseEvent.MOUSE_MOVE:
                        this._handle.onmousemove = null;
                        break;
                    case JFocus.type.MouseEvent.ROLL_OVER:
                        this._handle.onmouseover = null;
                        break;
                    case JFocus.type.MouseEvent.ROLL_OUT:
                        this._handle.onmouseout = null;
                        break;
                    case JFocus.type.KeyboardEvent.KEY_DOWN:
                        JFocus.keyboardManager.removeListener(JFocus.type.KeyboardEvent.KEY_DOWN, this, this._keyDownHandler);
                        break;
                    case JFocus.type.KeyboardEvent.KEY_UP:
                        JFocus.keyboardManager.removeListener(JFocus.type.KeyboardEvent.KEY_UP, this, this._keyUpHandler);
                        break;
                    case JFocus.type.KeyboardEvent.KEY_PRESS:
                        JFocus.keyboardManager.removeListener(JFocus.type.KeyboardEvent.KEY_PRESS, this, this._keyPressHandler);
                        break;
                }
            }
        };

        /**
        * 鼠标点击
        * @param event 事件对象
        **/
        this._clickHandler = function (event) {
            event = event ? event : window.event;

            var e = new JFocus.type.MouseEvent(JFocus.type.MouseEvent.CLICK);
            e.localX = event.layerX;
            e.localY = event.layerY;
            e.stageX = event.clientX;
            e.stageY = event.clientY;
            self.dispatchEvent(e);
        };

        /**
        * 鼠标松开
        * @param event 事件对象
        **/
        this._mouseUpHandler = function (event) {
            event = event ? event : window.event;

            var e = new JFocus.type.MouseEvent(JFocus.type.MouseEvent.MOUSE_UP);
            e.localX = event.layerX;
            e.localY = event.layerY;
            e.stageX = event.clientX;
            e.stageY = event.clientY;
            self.dispatchEvent(e);
        };

        /**
        * 鼠标按下
        * @param event 事件对象
        **/
        this._mouseDownHandler = function (event) {
            event = event ? event : window.event;

            var e = new JFocus.type.MouseEvent(JFocus.type.MouseEvent.MOUSE_DOWN);
            e.localX = event.layerX;
            e.localY = event.layerY;
            e.stageX = event.clientX;
            e.stageY = event.clientY;
            self.dispatchEvent(e);
        };

        /**
        * 鼠标移动
        * @param event 事件对象
        **/
        this._mouseMoveHandler = function (event) {
            event = event ? event : window.event;

            var e = new JFocus.type.MouseEvent(JFocus.type.MouseEvent.MOUSE_MOVE);
            e.localX = event.layerX;
            e.localY = event.layerY;
            e.stageX = event.clientX;
            e.stageY = event.clientY;
            self.dispatchEvent(e);
        };

        /**
        * 鼠标移入
        * @param event 事件对象
        **/
        this._rollOverHandler = function (event) {
            event = event ? event : window.event;

            var e = new JFocus.type.MouseEvent(JFocus.type.MouseEvent.ROLL_OVER);
            e.localX = event.layerX;
            e.localY = event.layerY;
            e.stageX = event.clientX;
            e.stageY = event.clientY;
            self.dispatchEvent(e);
        };

        /**
        * 鼠标移出
        * @param event 事件对象
        **/
        this._rollOutHandler = function (event) {
            event = event ? event : window.event;

            var e = new JFocus.type.MouseEvent(JFocus.type.MouseEvent.ROLL_OUT);
            e.localX = event.layerX;
            e.localY = event.layerY;
            e.stageX = event.clientX;
            e.stageY = event.clientY;
            self.dispatchEvent(e);
        };

        /**
        * 按键按下事件
        * @param event 事件对象
        **/
        this._keyDownHandler = function (event) {
            event = event ? event : window.event;

            var e = new JFocus.type.KeyboardEvent(JFocus.type.KeyboardEvent.KEY_DOWN);
            e.keyCode = event.keyCode;
            e.charCode = event.charCode;
            e.shiftKey = event.shiftKey;
            e.ctrlKey = event.ctrlKey;
            e.altKey = event.altKey;
            self.dispatchEvent(e);
        };

        /**
        * 按键松开事件
        * @param event 事件对象
        **/
        this._keyUpHandler = function (event) {
            event = event ? event : window.event;

            var e = new JFocus.type.KeyboardEvent(JFocus.type.KeyboardEvent.KEY_UP);
            e.keyCode = event.keyCode;
            e.charCode = event.charCode;
            e.shiftKey = event.shiftKey;
            e.ctrlKey = event.ctrlKey;
            e.altKey = event.altKey;
            self.dispatchEvent(e);
        };

        /**
        * 按键按压事件
        * @param event 事件对象
        **/
        this._keyPressHandler = function (event) {
            event = event ? event : window.event;

            var e = new JFocus.type.KeyboardEvent(JFocus.type.KeyboardEvent.KEY_PRESS);
            e.keyCode = event.keyCode;
            e.charCode = event.charCode;
            e.shiftKey = event.shiftKey;
            e.ctrlKey = event.ctrlKey;
            e.altKey = event.altKey;
            self.dispatchEvent(e);
        };

        /**
        * 应用程序的鼠标移动事件
        * @param e 事件对象
        **/
        this._applicationMouseMoveHandler = function (e) {
            self.x(self.parent.mouseX() + self._propertyManager.getValue("_offsetX"));
            self.y(self.parent.mouseY() + self._propertyManager.getValue("_offsetY"));
        };

        /**
        * 执行拖动
        * @param center 是否让对象中心点位于鼠标指向位置
        **/
        this._doDrag = function (center) {
            if (center) {
                this._propertyManager.changeValue("_offsetX", -this.width() / 2);
                this._propertyManager.changeValue("_offsetY", -this.height() / 2);
            } else {
                this._propertyManager.changeValue("_offsetX", this.x() - this.parent.mouseX());
                this._propertyManager.changeValue("_offsetY", this.y() - this.parent.mouseY());
            }
            //监听根对象移动事件
            this.root.addEventListener(JFocus.type.MouseEvent.MOUSE_MOVE, this._applicationMouseMoveHandler);
        };

        /**
        * 开始拖动
        * @param center 是否让对象中心点位于鼠标指向位置
        **/
        this.startDrag = function (center) {
            if (this.root != null) {
                this._doDrag(center);
            } else {
                //等待重绘时执行拖动
                this._propertyManager.changeValue("_canDrag", true);
                this._propertyManager.changeValue("_dragCenter", center);
            }
        };

        /**
        * 停止拖动
        **/
        this.stopDrag = function () {
            this.root.removeEventListener(JFocus.type.MouseEvent.MOUSE_MOVE, this._applicationMouseMoveHandler);
        };

        /**
        * 检测对象是否与指定点发生碰撞,传入坐标必须是场景坐标
        * @param x 点的横坐标
        * @param y 点的纵坐标
        * @return true表示产生碰撞，否则没有
        **/
        this.hitTestPoint = function (x, y) {
            if (this.parent != null) {
                var point = this.parent.localToGlobal(new JFocus.type.Point(this.x(), this.y()));
                if (point.x <= x && point.x + this.width() >= x && point.y <= y && point.y + this.height() >= y) {
                    return true;
                }
            }
            return false;
        };

        /**
        * 检测是否与对象产生碰撞
        * @param displayObject 显示对象
        * @return true表示产生碰撞，否则没有
        **/
        this.hitTest = function (displayObject) {
            if (displayObject instanceof JFocus.type.DisplayObject && this.parent != null) {
                var point1 = this.parent.localToGlobal(new JFocus.type.Point(this.x(), this.y()));
                var point2 = displayObject.parent.localToGlobal(new JFocus.type.Point(displayObject.x(), displayObject.y()));

                return !(point1.x > point2.x + displayObject.width() ||
					 point1.x + this.width() < point2.x ||
        			 point1.y + this.height() < point2.y ||
					 point1.y > point2.y + displayObject.height());
            }
            return false;
        };
    };
    JFocus.inherited(JFocus.type.Sprite, JFocus.type.DisplayObjectContainer);

    /**
    * 遮罩层
    **/
    JFocus.type.MaskLayer = function () {
        JFocus.type.DisplayObject.apply(this, [null]);

        this._propertyManager.initProperty({ _maskTarget: null });

        /**
        * 遮罩对象
        * @param value 遮罩对象，不传入此参数则表示获取遮罩对象
        **/
        this.maskTarget = function (value) {
            if (arguments.length > 0) {
                if (value instanceof JFocus.type.DisplayObject) {
                    this._propertyManager.changeValue("_maskTarget", value);
                }
            } else {
                return this._propertyManager.getValue("_maskTarget");
            }
        };

        /**
        * 顶点横坐标
        * @param value 坐标值，不传入此参数则表示获取横坐标值
        **/
        this.x = function (value) {
            if (arguments.length > 0) {
                if (this._propertyManager.changeValue("_x", value)) {
                    if (this.maskTarget() != null) {
                        //遮罩目标进行刷新
                        this.maskTarget().invalidate();
                    }
                }
            } else {
                return this._propertyManager.getValue("_x");
            }
        };

        /**
        * 顶点纵坐标
        * @param value 坐标值，不传入此参数则表示获取纵坐标值
        **/
        this.y = function (value) {
            if (arguments.length > 0) {
                if (this._propertyManager.changeValue("_y", value)) {
                    if (this.maskTarget() != null) {
                        //遮罩目标进行刷新
                        this.maskTarget().invalidate();
                    }
                }
            } else {
                return this._propertyManager.getValue("_y");
            }
        };

        /**
        * 宽度
        * @param value 宽度，不传入此参数则表示获取宽度
        **/
        this.width = function (value) {
            if (arguments.length > 0) {
                if (this._propertyManager.changeValue("_width", value)) {
                    if (this.maskTarget() != null) {
                        //遮罩目标进行刷新
                        this.maskTarget().invalidate();
                    }
                }
            } else {
                return this._propertyManager.getValue("_width");
            }
        };

        /**
        * 高度
        * @param value 高度，不传入此参数则表示获取高度
        **/
        this.height = function (value) {
            if (arguments.length > 0) {
                if (this._propertyManager.changeValue("_height", value)) {
                    if (this.maskTarget() != null) {
                        //遮罩目标进行刷新
                        this.maskTarget().invalidate();
                    }
                }
            } else {
                return this._propertyManager.getValue("_height");
            }
        };

        /**
        * 对象字符串
        * @return 对象字符串
        **/
        this.toString = function () {
            return "[MaskLayer maskLayer]";
        };
    };
    JFocus.inherited(JFocus.type.MaskLayer, JFocus.type.DisplayObject);

    /**
    * 图像类
    **/
    JFocus.type.Image = function (name, url) {
        JFocus.type.DisplayObject.apply(this, [name]);

        this._propertyManager.initProperty({ _hasAutoSize: true, _imageWidth: 0, _imageHeight: 0 });

        if (this._handle == null || this._handle.tagName != "IMG") {
            this._handle = new Image();
            this._handle.id = this._name;
            this._handle.name = this._name;
        }
        this._handle.style.position = "absolute";
        //使图片无法拖曳
        this._handle.ondragstart = function () {
            return false;
        };

        var self = this;

        if (JFocus.browser.ie) {
            //IE浏览器使用滤镜进行旋转
            this._drawRotationAndFrameFunc = function () {
                if (this.rotation() != 0) {
                    if (this._propertyManager.hasChanged("_rotation") || this._propertyManager.hasChanged("_x") || this._propertyManager.hasChanged("_y") || this._propertyManager.hasChanged("_width") || this._propertyManager.hasChanged("_heigh")) {
                        this._propertyManager.syncValue("_rotation");
                        this._propertyManager.syncValue("_x");
                        this._propertyManager.syncValue("_y");
                        this._propertyManager.syncValue("_width");
                        this._propertyManager.syncValue("_height");

                        var rad = this.rotation() * (Math.PI / 180);
                        var cosValue = Math.cos(rad);
                        var sinValue = Math.sin(rad);
                        //原始中心点
                        var srcCX = this.width() / 2;
                        var srcCY = this.height() / 2;

                        this._handle.style.filter = "progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand', M11=" + cosValue + ", M12=" + (-sinValue) + ", M21=" + sinValue + ", M22=" + cosValue + ")";

                        //转换后中心点
                        rect = this._handle.getBoundingClientRect();
                        var cx = (rect.right - rect.left) / 2;
                        var cy = (rect.bottom - rect.top) / 2;

                        this._handle.style.left = (this.x() + srcCX - cx) + "px";
                        this._handle.style.top = (this.y() + srcCY - cy) + "px";
                        if (!this._propertyManager.getValue("_hasAutoSize")) {
                            this._handle.style.width = this.width() + "px";
                            this._handle.style.height = this.height() + "px";
                        }
                    }
                } else {
                    this._handle.style.left = this.x() + "px";
                    this._handle.style.top = this.y() + "px";
                    if (!this._propertyManager.getValue("_hasAutoSize")) {
                        this._handle.style.width = this.width() + "px";
                        this._handle.style.height = this.height() + "px";
                    }
                }
            };

        } else {

            this._drawRotationAndFrameFunc = function () {
                this._handle.style.left = this.x() + "px";
                this._handle.style.top = this.y() + "px";
                if (!this._propertyManager.getValue("_hasAutoSize")) {
                    this._handle.style.width = this.width() + "px";
                    this._handle.style.height = this.height() + "px";
                }

                if (this._propertyManager.hasChanged("_rotation")) {
                    this._propertyManager.syncValue("_rotation");
                    this._handle.style.OTransform = " rotate(" + this.rotation() + "deg)"; 	//Opera
                    this._handle.style.WebkitTransform = " rotate(" + this.rotation() + "deg)"; //Webkit核心
                    this._handle.style.MozTransform = " rotate(" + this.rotation() + "deg)"; 	//火狐
                    this._handle.style.Transform = "rotate(" + this.rotation() + "deg)";
                }
            };
        }

        /**
        * 重绘对象
        **/
        this._redraw = function () {
            if (this._hasRedraw && this._handle != null) {
                this._drawRect();
                this._hasRedraw = false;
            }
        };

        /**
        * 绘画对象
        **/
        this._drawRect = function () {
            if (this.visible()) {
                this._handle.style.display = "block";

                this._drawRotationAndFrameFunc();

                if (this._propertyManager.hasChanged("_alpha")) {
                    this._propertyManager.syncValue("_alpha");

                    this._handle.style.filter = "Alpha(Opacity=" + this.alpha() + ")"; //IE中设置透明
                    this._handle.style.MozOpacity = this.alpha() / 100; 			//火狐
                    this._handle.style.opacity = this.alpha() / 100; 				//Webkit核心
                }

                //绘画遮罩
                if (this._propertyManager.hasChanged("_mask")) {
                    this._propertyManager.syncValue("_mask");

                    var maskObj = this.mask();
                    //判断是否有遮罩层
                    if (maskObj != null) {
                        //计算遮罩范围
                        var left = Math.max(this.x(), maskObj.x());
                        var right = Math.min(this.x() + this.width(), maskObj.x() + maskObj.width());
                        var top = Math.max(this.y(), maskObj.y());
                        var bottom = Math.min(this.y() + this.height(), maskObj.y() + maskObj.height());


                        if (left < right && top < bottom) {
                            top -= this._y;
                            bottom -= this._y;
                            left -= this._x;
                            right -= this._x;
                            this._handle.style.clip = "rect(" + top + "px " + right + "px " + bottom + "px " + left + "px)";
                            this._handle.style.clip = "rect(" + top + "px, " + right + "px, " + bottom + "px, " + left + "px)";
                        } else {
                            this._handle.style.clip = "rect(0px 0px 0px 0px)";
                            this._handle.style.clip = "rect(0px, 0px, 0px, 0px)";
                        }
                    } else {
                        this._handle.style.clip = "auto";
                    }
                }
            } else {
                this._handle.style.display = "none";
            }
        };

        /**
        * 完成事件处理器
        **/
        this._loadHandler = function (event) {
            self._propertyManager.changeValue("_imageWidth", self._handle.width);
            self._propertyManager.changeValue("_imageHeight", self._handle.height);
            if (self._propertyManager.getValue("_hasAutoSize")) {
                self._propertyManager.changeValue("_width", self._propertyManager.getValue("_imageWidth"));
                self._propertyManager.changeValue("_height", self._propertyManager.getValue("_imageHeight"));
            }

            self.invalidate();

            var e = new JFocus.type.Event(JFocus.type.Event.COMPLETE);
            self.dispatchEvent(e);
        };

        /**
        * @inheritDoc
        * 设置宽度后图片将不再自动调整尺寸
        **/
        this.width = function (value) {
            if (arguments.length > 0) {
                this._propertyManager.changeValue("_hasAutoSize", false);
                if (this._propertyManager.changeValue("_width", value)) {
                    this.invalidate();
                }
            } else {
                return this._propertyManager.getValue("_width");
            }
        };

        /**
        * @inheritDoc
        * 设置高度后图片将不再自动调整尺寸
        **/
        this.height = function (value) {
            if (arguments.length > 0) {
                this._propertyManager.changeValue("_hasAutoSize", false);
                if (this._propertyManager.changeValue("_height", value)) {
                    this.invalidate();
                }
            } else {
                return this._propertyManager.getValue("_height");
            }
        };

        /**
        * 图片宽度
        **/
        this.imageWidth = function () {
            return this._propertyManager.getValue("_imageWidth");
        };

        /**
        * 图片高度
        **/
        this.imageHeight = function () {
            return this._propertyManager.getValue("_imageHeight");
        };

        /**
        * 图片路径
        **/
        this.url = function (value) {
            if (arguments.length > 0) {
                this._handle.src = value;
            } else {
                return this._handle.src;
            }
        };

        if (url != null) {
            this._handle.src = url;
        }
        this._handle.onload = this._loadHandler;
    };
    JFocus.inherited(JFocus.type.Image, JFocus.type.DisplayObject);

    ///Region:Global

    /**
    * 主循环
    **/
    window.__mainRunLoop = function () {
        //派发进入帧事件
        var e = new JFocus.type.Event(JFocus.type.Event.ENTER_FRAME);
        JFocus.application.dispatchEvent(e);
        //进行重绘
        JFocus.application._redraw();
    };

    /**
    * 变更名称空间
    **/
    window.changeJFocusNameSpace = function (ns) {
        window[ns] = JFocus;
    };

    window.$jf = JFocus;
    window.JFocus = JFocus;
})(window);